#pragma once 
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <sstream>
#include <fstream>
#include <memory>

using namespace std;
string sep = "\r\n";
string hander_sep = ": ";
string wwwroot = "wwwroot";
string homepage = "index.html";
string httpversion = "HTTP/1.0";
string space = " ";
string suffixsep = ".";

class HttpRequest
{
    // 获取一大串中的一行，返回 => [正文] 或 [空\r\n]即sep 或 [空] 
    string getLine(string &reqstr)
    {
        if(reqstr.empty()) return reqstr;
        auto pos = reqstr.find(sep);
        if(pos == string::npos) return string();

        string line = reqstr.substr(0, pos);
        if(line.empty()) return sep;

        reqstr.erase(0, pos+sep.size());
        return line;
    }
    bool ParseHeaderHelper(string &line, string *k, string *v)
    {
        auto pos = line.find(hander_sep);
        if(pos == string::npos) return false;
        *k = line.substr(0, pos);
        *v = line.substr(pos+hander_sep.size());
        return true;
    }
public:
    HttpRequest():_blanck_line(sep), _path(wwwroot)
    {}

    // 反序列化
    void UnSerialize(string &reqstr)
    {   
        // 不管是什么，先给请求行
        _req_line = getLine(reqstr);
        while(true)
        {
            string line = getLine(reqstr);
            if(line.empty()) break;
            else if(line == sep)// 空行
            {
                _req_text = reqstr;// 后面都是正文
                break;
            }
            else 
            {
                _req_hander.push_back(line);
            }
        }
        ParseReqLine();
        ParseHeader();
    }

    void Print()
    {
        cout << "=== " << _req_line << endl;
        for(auto &e:_req_hander)
        {
            cout << "## " << e <<endl;
        }
        cout << _blanck_line;
        cout << _req_text << endl;

        // cout << "method: " << _method << endl;
        // cout << "url: " << _url << endl;
        // cout << "path: " << _path << endl;
        // cout << "version: " << _version << endl;

        // for(auto e:_handers)
        // {
        //     cout << "@@ " << e.first << " -- " << e.second << endl;
        // }
    }

    bool ParseReqLine()
    {
        if(_req_line.empty()) return false;
        stringstream ss(_req_line);
        ss >> _method >> _url >> _version;
        _path += _url;

        cout << "url: " << _url << endl;

        if(_path[_path.size()-1] == '/')
        {
            _path += homepage;
        }

        auto pos = _path.rfind(suffixsep);
        if(pos == string::npos)
        {
            _suffix = ".html";
        }
        else 
        {
            _suffix = _path.substr(pos);
        }

        return true;
    }

    bool ParseHeader()
    {
        for(auto &line:_req_hander)
        {
            string k, v;
            if(ParseHeaderHelper(line, &k, &v))
            {
                _handers.insert(make_pair(k, v));
            }
        }
        return true;
    }

    string getPath()
    {
        return _path;
    }

    string getSuffix()
    {
        return _suffix;
    }

    ~HttpRequest()
    {}

private:
    string _req_line;// 请求行
    vector<string> _req_hander;// 请求报头
    string _blanck_line;// 空行
    string _req_text;// 正文

    // 具体信息
    string _method;// 请求方法
    string _url;
    string _path;// 路径
    string _version;// 版本
    string _suffix;// 后缀

    unordered_map<string, string> _handers;
};

class HttpResponse
{
public:
    HttpResponse():_version(httpversion), _blanck_line(sep)
    {}

    void AddStatus()
    {
        _code = 200;
        _desc = "OK";
    }

    void AddHanders(const string &k, const string &v)
    {
        _handers[k] = v;
    }

    void AddText(const string &text)
    {
        _resp_text = text;
    }

    // 序列化
    string Serialize()
    {
        string statusline = _version + space + to_string(_code) + space + _desc + sep;
        for(auto &hander:_handers)
        {
            _resp_hander.emplace_back(hander.first + hander_sep + hander.second + sep);
        }
        // 开始序列化
        string respstr = statusline;
        for(auto &hander:_resp_hander)
        {
            respstr += hander;
        }
        respstr += _blanck_line;
        respstr += _resp_text;
        return respstr;
    }   

    ~HttpResponse()
    {}

private:
    string _resp_status;// 状态行
    vector<string> _resp_hander;// 响应报头
    string _blanck_line;// 空行
    string _resp_text;// 正文

    string _version;// 版本
    int _code;// 状态码
    string _desc;// 状态码描述
    unordered_map<string, string> _handers;// k v
};

class Http
{
public:
    Http()
    {}

    // 按照二进制打开
    string ReadFile(const string &path, int *size)
    {
        ifstream in(path, ios::binary);
        if(!in.is_open()) return string();

        in.seekg(0, in.end);
        int filesize = in.tellg();
        in.seekg(0, in.beg);

        string content;
        content.resize(filesize);
        in.read((char*)content.c_str(), filesize);// !!是content不是path
        in.close();

        *size = filesize;
        return content;
    }

    string Excute(string req)
    {
        HttpRequest request;
        // 对请求反序列化
        request.UnSerialize(req);
        request.Print();
        
        int contentsize = 0;// 正文长度
        string text = ReadFile(request.getPath(), &contentsize);// 获取正文
        string suffix = request.getSuffix();// 获取后缀

        // string text = "<html><h1><body>hello yss! hello world!</body></h1></html>";
        // int contentsize = text.size();

        HttpResponse response;
        // 获取字段
        response.AddStatus();
        response.AddHanders("Content-Length", to_string(contentsize));
        // response.AddHanders("Content-Type", "text/html");// 写死了
        response.AddHanders("Content-Type", _mine_type[suffix]);
        response.AddText(text);
        // 序列化
        return response.Serialize();
    }

    ~Http()
    {}

private:
    unordered_map<string, string> _mine_type;
};